﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using EventBus.Common;
using Microsoft.Extensions.DependencyInjection;

namespace EventBus.RabbitMQ
{
    /// <summary>
    /// 订阅者注册缓存
    /// </summary>
    public static class RegisterSubscriber
    {
        /// <summary>
        /// 注册Handler
        /// </summary>
        /// <param name="service"></param>
        /// <param name="assemblyName"></param>
        public static void RegisterHandler(this IServiceCollection service, Assembly[] assemblies, HandlerType handlerType)
        {
            if (!assemblies.Any()) 
            {
                throw new Exception("注册Handler,程序集不存在！");
            }
            var types = RuntimeHelper.GetAllTypes(assemblies);
            switch (handlerType)
            {
                case HandlerType.CommandHandler:
                    InjectionCommandHandler(service, types);
                    break;
                case HandlerType.EventHandler:
                    InjectionEventHandler(service, types);
                    break;
                case HandlerType.AllHandler:
                    InjectionCommandHandler(service, types);
                    InjectionEventHandler(service, types);
                    break;
                default:
                    break;
            }

        }

        public static void InjectionCommandHandler(IServiceCollection service, List<Type> types) 
        {
            var commandHandlerTypes = types.Where(t => t.GetTypeInfo().IsClass
                                      && t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == GetGenericCommandHandlerType()));
            
            foreach (var type in commandHandlerTypes)
            {
                var Interfaces = type.GetInterfaces().FirstOrDefault();
                service.AddSingleton(Interfaces, type);
            }
        }

        public static void InjectionEventHandler(IServiceCollection service, List<Type> types)
        {
            var eventHandlerTypes = types.Where(t => t.GetTypeInfo().IsClass
                                    && t.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == GetGenericEventHandlerType()));
            
            foreach (var type in eventHandlerTypes)
            {
                var Interfaces = type.GetInterfaces().FirstOrDefault();
                service.AddSingleton(Interfaces, type);
            }
        }

        /// <summary>
        /// 获取CommandHandler的类型
        /// </summary>
        /// <returns></returns>
        public static Type GetGenericCommandHandlerType()
        {
            return typeof(ICommandHandler<>);
        }

        /// <summary>
        ///   /// <summary>
        /// 获取EventHandler的类型
        /// </summary>
        /// <returns></returns>
        /// </summary>
        /// <returns></returns>
        public static Type GetGenericEventHandlerType()
        {
            return typeof(IEventHandler<>);
        }

    }

    public enum HandlerType 
    {
        CommandHandler,
        EventHandler,
        AllHandler
    }
}
